﻿using System;
using System.Web.Security;

namespace AidBrella.CustomStuff
{
    /// <summary>
    /// adapted from http://theintegrity.co.uk/2010/11/asp-net-mvc-2-custom-membership-provider-tutorial-part-3/
    /// </summary>
    public interface IMembershipService
    {
        int MinPasswordLength { get; }
        bool ValidateUser(string userName, string password);
        bool ValidateUserByEmail(string email, string password);
        MembershipCreateStatus CreateUser(string userName, string password, string email, string firstName, string lastName);
        // MembershipCreateStatus CreateUser(string email, string password, string firstName, string lastName);
        bool ChangePassword(string userName, string oldPassword, string newPassword);
        string GetUserName(string email);
    }

    public class AidBrellaAccountManagementService : IMembershipService
    {

        private readonly MembershipProvider _provider;


        public AidBrellaAccountManagementService()
            : this(null)
        {
        }

        public AidBrellaAccountManagementService(MembershipProvider provider)
        {
            _provider = provider ?? Membership.Provider;
        }

        /// <summary>
        /// Minimum accepted password length in aidbrella 
        /// </summary>
        public int MinPasswordLength
        {
            get { return _provider.MinRequiredPasswordLength; }
        }

        public bool ValidateUser(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName))
                throw new ArgumentException("Value cannot be null or empty.", "userName");
            if (String.IsNullOrEmpty(password))
                throw new ArgumentException("Value cannot be null or empty.", "password");

          
            return _provider.ValidateUser(userName, password);
        }

        /// <summary>
        /// Validates User by supplied email
        /// </summary>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool ValidateUserByEmail(string email, string password)
        {
            if (String.IsNullOrEmpty(email))
                throw new ArgumentException("Value cannot be null or empty.", "email");
            if (String.IsNullOrEmpty(password))
                throw new ArgumentException("Value cannot be null or empty.", "password");

            string userName = _provider.GetUserNameByEmail(email);
            if (!string.IsNullOrEmpty(userName))
                return _provider.ValidateUser(userName, password);
            else
                return false;
        }

        public MembershipCreateStatus CreateUser(string userName, string password, string email, string firstName, string lastName)
        {

            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
            if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
            if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
            if (String.IsNullOrEmpty(firstName)) throw new ArgumentException("Value cannot be null or empty.", "firstName");
            if (String.IsNullOrEmpty(lastName)) throw new ArgumentException("Value cannot be null or empty.", "lastName");

            MembershipCreateStatus status;

            _provider.CreateUser(userName, password, email, firstName, lastName, true, null, out status);
            return status;
        }

        /// <summary>
        /// returns MembershipCreateStatus for supplied Parameters
        /// </summary>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        /// <returns></returns>
        //public MembershipCreateStatus CreateUser(string email, string password, string firstName, string lastName)
        //{
        //    throw new NotImplementedException();
        //}

        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
            if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("Value cannot be null or empty.", "oldPassword");
            if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("Value cannot be null or empty.", "newPassword");

            // The underlying ChangePassword() will throw an exception rather
            // than return false in certain failure scenarios.
            try
            {
                MembershipUser currentUser = _provider.GetUser(userName, true /* userIsOnline */);
                return currentUser.ChangePassword(oldPassword, newPassword);
            }
            catch (ArgumentException)
            {
                return false;
            }
            catch (MembershipPasswordException)
            {
                return false;
            }
        }

        /// <summary>
        /// Returns UserName (Fname + Lname) based on email
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public string GetUserName(string email)
        {
            return _provider.GetUserNameByEmail(email);
        }

       
    }

    public interface IFormsAuthenticationService
    {
        void SignIn(string userName, bool createPersistentCookie);
        void SignOut();
    }

    public class FormsAuthenticationService : IFormsAuthenticationService
    {
        public void SignIn(string userName, bool createPersistentCookie)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");

            FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
        }

        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }

    public static class AccountValidation
    {
        public static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // See http://go.microsoft.com/fwlink/?LinkID=177550 for
            // a full list of status codes.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "Username already exists. Please enter a different user name.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "A username for that e-mail address already exists. Please enter a different e-mail address.";

                case MembershipCreateStatus.InvalidPassword:
                    return "The password provided is invalid. Please enter a valid password value.";

                case MembershipCreateStatus.InvalidEmail:
                    return "The e-mail address provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "The password retrieval answer provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "The password retrieval question provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidUserName:
                    return "The user name provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.ProviderError:
                    return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                case MembershipCreateStatus.UserRejected:
                    return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
            }
        }
    }
}
    
